﻿using System;
using System.Web.Hosting;
using System.Collections.Specialized;
using System.Collections;
using System.Web.Caching;
using System.IO;
using System.Web;
using System.Collections.Generic;
using System.Reflection;
using EPiServer.Web.Hosting;

namespace EPiServer.CdnSupport.Test
{
    /// <summary>
    /// Default implementation of the IHostingEnvironment interface. It delegates to the ASP.NET
    /// HostingEnvironment class to do the "real" work.
    /// </summary>
    public class UnitTestHostingEnvironment : IHostingEnvironment
    {
        private List<VirtualPathProvider> _virtualPathProviders = new List<VirtualPathProvider>();

        public UnitTestHostingEnvironment()
        {
            _virtualPathProviders.Add(new FallbackVirtualPathProvider(this));
        }

        #region IHostingEnvironment Members

        public void RegisterVirtualPathProvider(VirtualPathProvider virtualPathProvider)
        {
            InitializeVPP(virtualPathProvider);
            _virtualPathProviders.Add(virtualPathProvider);
        }

        public VirtualPathProvider VirtualPathProvider
        {
            get { return _virtualPathProviders[_virtualPathProviders.Count - 1]; }
        }

        public string MapPath(string virtualPath)
        {
            return Path.Combine(ApplicationPhysicalPath, VirtualPathUtility.ToAbsolute(virtualPath, ApplicationVirtualPath).Replace('/', '\\'));
        }

        public string ApplicationID
        {
            get { return String.Empty; }
        }

        public string ApplicationPhysicalPath
        {
            get { return System.Environment.CurrentDirectory; }
        }

        public string ApplicationVirtualPath
        {
            get { return "/"; }
        }

        #endregion

        private void InitializeVPP(VirtualPathProvider virtualPathProvider)
        {
            //Calling initialize will set Previous property
            MethodInfo initializeMethod = typeof(VirtualPathProvider).GetMethod("Initialize", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, new Type[] { typeof(VirtualPathProvider) }, null);
            initializeMethod.Invoke(virtualPathProvider, new object[] { VirtualPathProvider }); ;
        }

        /// <summary>
        /// This is a stripped-down rip-off of System.Web.Hosting.MapPathBasedVirtualPathProvider which is used as a fallback provider.
        /// </summary>
        private class FallbackVirtualPathProvider : VirtualPathProvider
        {
            private IHostingEnvironment _hostingEnvironment;

            public IHostingEnvironment HostingEnv
            {
                get { return _hostingEnvironment; }
                set { _hostingEnvironment = value; }
            }

            public FallbackVirtualPathProvider(IHostingEnvironment hostingEnvironment)
            {
                this.HostingEnv = hostingEnvironment;
            }

            // Methods
            public override bool DirectoryExists(string virtualDir)
            {
                return Directory.Exists(HostingEnv.MapPath(virtualDir));
            }

            public override bool FileExists(string virtualPath)
            {
                return File.Exists(HostingEnv.MapPath(virtualPath));
            }

            public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
            {
                if (virtualPathDependencies == null)
                {
                    return null;
                }
                StringCollection strings = null;
                foreach (string str in virtualPathDependencies)
                {
                    string str2 = HostingEnv.MapPath(str);
                    if (strings == null)
                    {
                        strings = new StringCollection();
                    }
                    strings.Add(str2);
                }
                if (strings == null)
                {
                    return null;
                }
                string[] array = new string[strings.Count];
                strings.CopyTo(array, 0);
                return new CacheDependency(array, null, utcStart);
            }

            public override VirtualDirectory GetDirectory(string virtualDir)
            {
                return null;
            }

            public override VirtualFile GetFile(string virtualPath)
            {
                return null;
            }
        }
    }
}
